//
// Created by 13562 on 2024/1/6.
//

#ifndef SRC_STREAMFACTORY_H
#define SRC_STREAMFACTORY_H

#include "opencv2/opencv.hpp"
#include "Chrono.h"
#include "thread"
#include <string>
#include <vector>
#include <fstream>
#include <dirent.h>
#include <mutex>
#include <chrono>
#include <future>


using namespace std;


class StreamFactory {
private:
	Chrono chrono;
	cv::Mat currLeftFrame;
	cv::Mat currRightFrame;

	std::chrono::duration<long, std::milli> timeCost{};
	vector<string> fileNames;
	vector<uint64_t> timestamps;
	unsigned short tsPrecision{};
	string tsFileUrl;
	string leftFrameDirectory;
	string rightFrameDirectory;
	string fileNamePattern;
	string fileSuffix;
	string timeBaseStr;
	string timeFormat;
	ulong startIndex;
	ulong endIndex;
	short timeShift = 0;
	chrono::system_clock::time_point timeBase;
	uint64_t timestamp_nanos{};
	mutex mtx;
	double fps = 0;
	double dpf = 0;

	unsigned long frameCounts = 0;
	unsigned long currFrameIndex = 0;
	bool enabled = false;

	typedef enum { MANUALLY, AUTOMATICALLY } ShowThreadReturn;

	promise<StreamFactory::ShowThreadReturn> showThreadReturn;

	typedef enum { APPROX_TIME, SYNCED_TIME } TimeMode;

	TimeMode timeMode{};

	/**
	 * 获取文件全文
	 * @param file
	 * @return
	 */
	static stringstream readFile(const std::string &file);

	/**
	 * 加载配置
	 * @param configFile
	 */
	void loadConfig(const string &configFile);

	/**
	 * 加载时间戳文件
	 * @param tsFile
	 */
	void loadTimestamps(const string &tsFile);

	/**
	 * thread-call *
	 * 更新当前帧变量
	 */
	void updateImage();
	/**
	 * 读取vector<string> fileNames中位于index的图像文件到左右帧
	 * @param index
	 */
	void readFrame(unsigned long index);

	long setTimestamp();
	/**
	 * 清空当前帧
	 */
	void clearFrames();

	/**
	 * thread-call *
	 * 利用OpenCV窗口实时显示图像
	 * @param windows vector<pair<const string&, cv::Mat&>> 包含窗口名和帧引用的vector
	 * @return
	 */
	static ShowThreadReturn showImage(const vector<pair<const string&, cv::Mat&>>& windows);

	/**
	 * 根据所给的目录，文件名pattern，后缀获取一个包含目标文件名的vector(不包含目录部分)
	 * @param directory
	 * @param namePattern
	 * @param suffix
	 * @return
	 */
	static vector<string> getFiles(const string & directory, const string &namePattern , const string &suffix);

	/**
	 * 构建文件Url
	 * @param directory
	 * @param fileName
	 * @return
	 */
	static string getFileUrl(const string &directory, const string &fileName);

	/**
	 * 读取图像文件到帧变量
	 * @param frame 目标Mat引用
	 * @param imageFile 源文件
	 */
	static void read(cv::Mat& frame, const string &imageFile);

public:
	bool EXIT_SIGNAL = false;
	bool echo = false;

	/**
	 * 初始化流工厂
	 * @param configFile
	 */
	void init(const string &configFile);

	/**
	 * 接收一个vector<string> &winNames, 定义左右图像显示的窗口标题
	 * 新开线程显示图像
	 * @param winNames
	 */
	void showFrames(const vector<string>& winNames);

	/**
	 * 使能，更改活动状态
	 */
	void enable();

	/**
	 * 停用，更改活动状态
	 */
	void disable();

	/**================================================ Getters ============================================================*/
	unsigned int getDpf() const;
	double getFps() const;
	unsigned long getFrameCounts() const;
	unsigned long getCurrFrameIndex() const;
	const string &getLeftFrameDirectory() const;
	const string &getRightFrameDirectory() const;
	const string &getFileNamePattern() const;
	const string &getFileSuffix() const;
	const cv::Mat &getCurrLeftFrame() const;
	const cv::Mat &getCurrRightFrame() const;
	uint64_t getCurrTimestamp() const;
	bool isEnabled() const;
};


#endif //SRC_STREAMFACTORY_H
